﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Collections.Specialized;
using System.Windows.Forms;
using SharedLib;
namespace SharedLib.WinFormMVCFramework
{
    public class LanguageManager
    {
        Dictionary<string, List<string>> _languages = new Dictionary<string, List<string>>();
        StringDictionary _textDict = new StringDictionary();
        string _folder;

        //public event EventHandler<GenericEventArgs<string>> LanguageChanged;

        public LanguageManager(string languageFolder)
        {
            _folder = languageFolder;
        }

        public ICollection<string> SupportedLanguages
        {
            get { return _languages.Keys; }
        }

        private string _currentLanguage = "default";
        public string CurrentLanguage
        {
            get { return _currentLanguage; }
            set
            {
                string input = value;
                if (String.IsNullOrEmpty(input))
                {
                    input = "default";
                }

                if (_currentLanguage != input)
                {
                    _currentLanguage = input;
                    //Switch language
                    LoadLanguage(_currentLanguage);
                    //LanguageChanged.InvokeEvent(this, new GenericEventArgs<string>(input));
                }
            }
        }

        public void LoadSettings()
        {
            foreach (string fileName in Directory.EnumerateFiles(_folder, "*.xml"))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(fileName);
                XmlElement languageNode = doc.SelectSingleNode("/language") as XmlElement;
                if (languageNode != null)
                {
                    string languageName = languageNode.GetAttribute("name");
                    if(!String.IsNullOrEmpty(languageName)){
                        List<string> fileList;
                        if (!_languages.ContainsKey(languageName))
                        {
                            fileList = new List<string>();
                            _languages[languageName] = fileList;
                        }
                        else
                        {
                            fileList = _languages[languageName];
                        }
                        fileList.Add(fileName);
                    }
                }
            }
        }

        private void LoadLanguage(string languageName)
        {
            if (languageName == "default")
            {
                _textDict = new StringDictionary();
            }
            else
            {
                if (_languages.ContainsKey(languageName))
                {
                    foreach (string fileName in _languages[languageName])
                    {
                        LoadLanguageFile(fileName);
                    }
                }
                else
                {
                    throw new ArgumentException("Language not supported: " + languageName);
                }
            }
        }

        private void LoadLanguageFile(string filename)
        {
            if (File.Exists(filename))
            {
                try
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(filename);
                    //Form resources
                    foreach (XmlElement formNode in doc.SelectNodes("/language/form"))
                    {
                        string formName = formNode.GetAttribute("name");
                        string formText = formNode.GetAttribute("text");
                        if (!String.IsNullOrEmpty(formName))
                        {
                            if (!String.IsNullOrEmpty(formText))
                            {
                                _textDict["Form\\" + formName] = formText;
                            }
                            foreach (XmlElement controlNode in formNode.SelectNodes("control"))
                            {
                                string controlName = controlNode.GetAttribute("name");
                                string controlText = controlNode.GetAttribute("text");
                                if (!String.IsNullOrEmpty(controlName))
                                {
                                    _textDict["Form\\" + formName + "\\" + controlName] = controlText ?? String.Empty;
                                }
                            }
                        }
                    }
                    //Text resources
                    foreach (XmlElement textNode in doc.SelectNodes("/language/string"))
                    {
                        string strName = textNode.GetAttribute("name");
                        string strText = textNode.GetAttribute("text");
                        if (!String.IsNullOrEmpty(strName))
                        {
                            _textDict["Text\\" + strName] = strText ?? String.Empty;
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new ArgumentException("Failed to load language" + filename + " : ", ex);
                }
            }
            else
            {
                throw new FileNotFoundException("Language file not found", filename);
            }
        }

        public string GetText(string strName)
        {
            string key = "Text\\" + strName;
            if (_textDict.ContainsKey(key)) return _textDict[key];
            return strName;
        }

        public string GetText(string formName, string controlName)
        {
            string key;
            if (controlName == null) key = "Form\\" + formName;
            else key = "Form\\" + formName + "\\" + controlName;
            if (_textDict.ContainsKey(key)) return _textDict[key];
            return null;
        }

        public void ApplyLanguage(Form form)
        {
            if (form != null)
            {
                string text = GetText(form.Name, null);
                if(text != null) form.Text = text;
                foreach (Control c in form.Controls)
                {
                    ApplyLanguage(form.Name, c);
                }
            }
        }

        public void ApplyLanguage(string formName, ToolStripItem item)
        {
            if (item != null && !String.IsNullOrEmpty(formName))
            {
                string text = GetText(formName, item.Name);
                if (text != null) item.Text = text;
                if (item is ToolStripMenuItem)
                {
                    foreach (ToolStripItem subItem in ((ToolStripMenuItem)item).DropDownItems)
                    {
                        ApplyLanguage(formName, subItem);
                    }
                }
            }
        }

        public void ApplyLanguage(string formName, Control c)
        {
            if (c != null && !String.IsNullOrEmpty(formName))
            {
                string text;
                switch (c.GetType().Name)
                {
                    case "Label":
                    case "TextBox":
                    case "CheckBox":
                    case "Button":
                    case "ToolStripButton":
                    case "ToolStripStatusLabel":
                    case "ToolStripLabel":
                    case "ToolStripTextBox":
                        text = GetText(formName, c.Name);
                        if (text != null) c.Text = text;
                        break;
                    case "ToolStripContainer":
                    case "ToolStripPanel":
                    case "ToolStripContentPanel":
                    case "SplitterPanel":
                    case "SplitContainer":
                    case "FlowLayoutPanel":
                        foreach (Control sub in c.Controls)
                        {
                            ApplyLanguage(formName, sub);
                        }
                        break;
                    case "ToolStrip":
                    case "StatusStrip":
                    case "ContextMenuStrip":
                        foreach (ToolStripItem item in ((ToolStrip)c).Items)
                        {
                            ApplyLanguage(formName, item);
                        }
                        break;
                    case "GroupBox":
                        text = GetText(formName, c.Name);
                        if (text != null) c.Text = text;
                        foreach (Control sub in c.Controls)
                        {
                            ApplyLanguage(formName, sub);
                        }
                        break;
                }

                if (c.ContextMenuStrip != null)
                {
                    ApplyLanguage(formName, c.ContextMenuStrip);
                }
                
            }
        }
    }
}
